package com.j4cf.web.aspect;

import com.alibaba.fastjson.JSON;
import com.j4cf.auth.dao.entity.AuthLog;
import com.j4cf.auth.service.AuthApiService;
import com.j4cf.common.util.RequestUtil;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang.ObjectUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.lang.reflect.Method;
import java.util.Map;

/**
 * @Description:
 * @Author: LongRou
 * @CreateDate: 2018 2018/5/8 17:25
 * @Version: 1.0
 **/
@Aspect
@Component
public class LogAspect {
    
    private static final Logger LOGGER = LoggerFactory.getLogger(LogAspect.class);

    // 开始时间
    private long startTime = 0L;
    // 结束时间
    private long endTime = 0L;
    @Autowired
    @Lazy
    private AuthApiService authApiService;
    /**
     * AOP规则定义 execution  @annotation
     */
    @Pointcut("execution(* *..controller..*.*(..))")
    public void controllerMethodPointcut(){}

    @Before("controllerMethodPointcut()")
    public void doBeforeInServiceLayer(JoinPoint joinPoint) {
        LOGGER.debug("doBeforeInServiceLayer");
        startTime = System.currentTimeMillis();
    }

    @After("controllerMethodPointcut()")
    public void doAfterInServiceLayer(JoinPoint joinPoint) {
        LOGGER.debug("doAfterInServiceLayer");
    }

    
    @Around("controllerMethodPointcut()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
        // 获取request
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
        HttpServletRequest request = servletRequestAttributes.getRequest();

        AuthLog authLog = new AuthLog();
        // 从注解中获取操作名称、获取响应结果
        Object result = pjp.proceed();
        Signature signature = pjp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        Method method = methodSignature.getMethod();
        if (method.isAnnotationPresent(ApiOperation.class)) {
            ApiOperation log = method.getAnnotation(ApiOperation.class);
            authLog.setDescription(log.value());
        }
        if (method.isAnnotationPresent(RequiresPermissions.class)) {
            RequiresPermissions requiresPermissions = method.getAnnotation(RequiresPermissions.class);
            String[] permissions = requiresPermissions.value();
            if (permissions.length > 0) {
                authLog.setPermissions(permissions[0]);
            }
        }
        endTime = System.currentTimeMillis();
        LOGGER.debug("doAround>>>result={},耗时：{}", result, endTime - startTime);

        authLog.setBasePath(RequestUtil.getBasePath(request));
        authLog.setIp(RequestUtil.getIpAddr(request));
        authLog.setMethod(request.getMethod());
        if ("GET".equalsIgnoreCase(request.getMethod())) {
            authLog.setParameter(request.getQueryString());
        } else {
            authLog.setParameter(ObjectUtils.toString(request.getParameterMap()));
            authLog.setResult(JSON.toJSONString(result));
        }
        authLog.setSpendTime((int) (endTime - startTime));
        authLog.setStartTime(startTime);
        authLog.setUri(request.getRequestURI());
        authLog.setUrl(ObjectUtils.toString(request.getRequestURL()));
        authLog.setUserAgent(request.getHeader("User-Agent"));
        authLog.setUsername(ObjectUtils.toString(request.getUserPrincipal()));
        authApiService.insertAuthLogSelective(authLog);
        return result;
    }
}
